
/*
 * Copyright (C) 2015-2018 Alibaba Group Holding Limited
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "common.h"
#include "esp_log.h"

#include "conn_mgr.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "esp_log.h"
#include "driver/gpio.h"
#include "esp_intr_alloc.h"

#include "sdkconfig.h"
#include "esp_task_wdt.h"

#include "mqtt_api.h"
#include "dm_wrapper.h"

#include "cJSON.h"

#define CONFIG_MAX_TEMPERATURE 2000 

void *pclient = NULL;
static const char *TAG = "temp_upstream";
char HIGHEST_TEMP_TAG[100] = "maxTemperature";

const int maxTemperatureErr = -1;

int update_count = 0;

char DEMO_PRODUCT_KEY[IOTX_PRODUCT_KEY_LEN + 1] = {0};
char DEMO_DEVICE_NAME[IOTX_DEVICE_NAME_LEN + 1] = {0};
char DEMO_DEVICE_SECRET[IOTX_DEVICE_SECRET_LEN + 1] = {0};

#define EXAMPLE_TRACE(fmt, ...)  \
    do { \
        HAL_Printf("%s|%03d :: ", __func__, __LINE__); \
        HAL_Printf(fmt, ##__VA_ARGS__); \
        HAL_Printf("%s", "\r\n"); \
    } while(0)

int light_publish(void *handle,int temperature); // rename

static void configure_key(void)
{
    // ESP_LOGI(TAG, "Example configured to blink GPIO LED!");
    // gpio_set_level(KEY_GPIO, led_state_off);
    /* Set the GPIO as a push/pull output */
    gpio_set_direction(KEY_GPIO, GPIO_MODE_INPUT);
}


static void handle_key_scan(void) //////// restore调试注释恢复
{
    ESP_LOGI(TAG, "正在重置WIFI\n");
    reset_wifi(1); //重置WIFI
    esp_restart(); //重启
}

static void key_scan(void)
{
    uint8_t key_tmp = 0;
    // ESP_LOGI(TAG, "Example configured to blink GPIO LED!");
    key_tmp = gpio_get_level(KEY_GPIO);
    if (key_tmp == KEY_PRESSED){
        while (key_tmp == KEY_PRESSED){
            key_tmp = gpio_get_level(KEY_GPIO);
            vTaskDelay(10 / portTICK_PERIOD_MS);
            esp_task_wdt_reset();
        }
        handle_key_scan(); // 按键处理
            // print_log();
    }
}


void process_key_value(char *key, int valueT) {
    // if (strcmp(key, "status") == 0) {
    //     if (strcmp(value, "on") == 0) {
    //         gpio_set_level(LED_GPIO, ON);
    //         EXAMPLE_TRACE("开灯状态已设置\n");
    //         light_publish(pclient, onlineStatOn);
    //     } else if (strcmp(value, "off") == 0) {
    //         gpio_set_level(LED_GPIO, OFF);
    //         EXAMPLE_TRACE("关灯状态已设置\n");
    //         light_publish(pclient, onlineStatOff);
    //     }
    // }
    // 使用指针来存储maxTemperature  
    int *maxTemperaturePtr = (int *)malloc(sizeof(int)); 
     
    if (strcmp(key, "status") == 0) {
        if (valueT == *maxTemperaturePtr) {
            EXAMPLE_TRACE("温度值相同，无需设置\n");
        } else if (valueT != *maxTemperaturePtr) {
            *maxTemperaturePtr = valueT;
            int ret = HAL_Kv_Set_Int(HIGHEST_TEMP_TAG, *maxTemperaturePtr);
            if(ret == ESP_FAIL){
                EXAMPLE_TRACE("设置失败");
            }
            EXAMPLE_TRACE("设置成功，最高温度: %02d.%02d 摄氏度", 
            *maxTemperaturePtr / 100, *maxTemperaturePtr % 100);
        }
    }

    free(maxTemperaturePtr);
}
void print_key_value(cJSON *item, const char *parent_key) {
    cJSON *child = NULL;
    if (cJSON_IsObject(item) || cJSON_IsArray(item)) {
        cJSON_ArrayForEach(child, item) {
            print_key_value(child, child->string); // 使用child->string作为键
        }
        
    } else if (cJSON_IsString(item)) {
        const char *key = item->string; // 使用item->string作为键
        const char *valueJSON = item->valuestring;
        printf("Key: %s, Value: %s\n", key, valueJSON);
    } else if (cJSON_IsNumber(item)) {
        const char *key = item->string; // 使用item->string作为键
        int valueJSON = item->valueint; // 对于整数类型的值
        printf("Key: %s, Value: %d\n", key, valueJSON);
        process_key_value(key, valueJSON);
    } else {
        printf("Key: %s, Value: %s\n", parent_key, "null");
    }
}

void light_message_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) // rename
{
    iotx_mqtt_topic_info_t     *topic_info = (iotx_mqtt_topic_info_pt) msg->msg;


    switch (msg->event_type) {
        case IOTX_MQTT_EVENT_PUBLISH_RECEIVED:
            /* print topic name and topic message */
            EXAMPLE_TRACE("Message Arrived:");
            EXAMPLE_TRACE("Topic  : %.*s", topic_info->topic_len, topic_info->ptopic);
            EXAMPLE_TRACE("Payload: %.*s", topic_info->payload_len, topic_info->payload);
            EXAMPLE_TRACE("---\n");


            const char *json_string = topic_info->payload;  
            cJSON *root = cJSON_Parse(json_string);  
        
            if (root == NULL) {  
                printf("Error before: [%s]\n", cJSON_GetErrorPtr());  
            }  
            // EXAMPLE_TRACE("重置WIFI\n");
            cJSON *operation_object = cJSON_GetObjectItemCaseSensitive(root, "operation");  

            // 检查键 "params" 是否为JSON_Object  
            if (!cJSON_IsString(operation_object)) {
                cJSON_Delete(root);
            } else if (strcmp(operation_object->valuestring, "setMaxTemperature") == 0) {
                EXAMPLE_TRACE("重置WIFI\n");
                cJSON *requireParams_object = cJSON_GetObjectItemCaseSensitive(root, "requireParams");
                if (!cJSON_IsString(requireParams_object) || strcmp(requireParams_object->valuestring, "false") == 0) {
                    cJSON_Delete(root);
                } else {
                    EXAMPLE_TRACE("重置WIFI\n");
                    cJSON *params_object = cJSON_GetObjectItemCaseSensitive(root, "params");
                    if (!cJSON_IsObject(params_object)) {
                        cJSON_Delete(root);
                    } else {
                        EXAMPLE_TRACE("重置WIFI\n");
                        print_key_value(params_object, NULL); // rename
                    }
                }
            } else if (strcmp(operation_object->valuestring, "resetWifi") == 0) {
                 EXAMPLE_TRACE("重置WIFI\n");
                reset_wifi(1);
                esp_restart();
                EXAMPLE_TRACE("重置WIFI\n");
            } else if (strcmp(operation_object->valuestring, "reboot") == 0) {
                EXAMPLE_TRACE("重启\n");
                esp_restart();
                EXAMPLE_TRACE("重启\n");
            } else {
                EXAMPLE_TRACE("错误\n");
                //print_key_value(root, NULL);
            }

        //     // 检查键 "status" 是否为整型  
        //     if (status_item->type != cJSON_Number) {  
        //         EXAMPLE_TRACE("Key 'status' is not an integer\n");  
        //         // cJSON_Delete(root);  
        //     } 
        //     else if(status_item->valueint == onlineStatOn){
        //         gpio_set_level(LED_GPIO, ON);
        //         EXAMPLE_TRACE("开灯状态已设置\n");
        //         light_publish(pclient,onlineStatOn);                
        //     } 
        //     else if(status_item->valueint == onlineStatOff){
        //         gpio_set_level(LED_GPIO, OFF);
        //         EXAMPLE_TRACE("关灯状态已设置\n");
        //         light_publish(pclient,onlineStatOff);                
        //     } 

            break;
        default:
            break;

        // // 释放资源  
        cJSON_Delete(root); 


    }
}





int light_subscribe(void *handle) // rename
{
    int res = 0;
    const char *fmt = "/sys/%s/%s/thing/service/property/set"; // /sys/k0yrr8izMtu/${deviceName}/thing/service/property/set
    char *topic = NULL;
    int topic_len = 0;

    topic_len = strlen(fmt) + strlen(DEMO_PRODUCT_KEY) + strlen(DEMO_DEVICE_NAME) + 1;
    topic = HAL_Malloc(topic_len);
    if (topic == NULL) {
        EXAMPLE_TRACE("memory not enough");
        return -1;
    }
    memset(topic, 0, topic_len);
    HAL_Snprintf(topic, topic_len, fmt, DEMO_PRODUCT_KEY, DEMO_DEVICE_NAME);

    res = IOT_MQTT_Subscribe(handle, topic, IOTX_MQTT_QOS0, light_message_arrive, NULL);
    if (res < 0) {
        EXAMPLE_TRACE("subscribe failed");
        HAL_Free(topic);
        return -1;
    }

    HAL_Free(topic);
    return 0;
}

int light_publish(void *handle, int temperature) {  
    int res = 0;  
    const char *fmt = "/sys/%s/%s/thing/event/property/post";  
    char *topic = NULL;  
    int topic_len = 0;  
    cJSON *root = NULL;  
    char *payload = NULL;

    topic_len = strlen(fmt) + strlen(DEMO_PRODUCT_KEY) + strlen(DEMO_DEVICE_NAME) + 1;
    topic = HAL_Malloc(topic_len);
    if (topic == NULL) {
        EXAMPLE_TRACE("memory not enough");
        return -1;
    }
    memset(topic, 0, topic_len);
    HAL_Snprintf(topic, topic_len, fmt, DEMO_PRODUCT_KEY, DEMO_DEVICE_NAME);


    // 使用指针来存储maxTemperature  
    int *maxTemperaturePtr = (int *)malloc(sizeof(int));  
    if (maxTemperaturePtr == NULL) {  
        EXAMPLE_TRACE("memory not enough for maxTemperature");  
        return -1;  
    }  

    int ret = HAL_Kv_Get_Int(HIGHEST_TEMP_TAG, (int32_t *)maxTemperaturePtr);
    if (ret != ESP_OK) {  
        EXAMPLE_TRACE("获取maxTemperature失败,%d", ret);  
        // 如果获取失败，重新设置默认值  
        *maxTemperaturePtr = CONFIG_MAX_TEMPERATURE;  
        ret = HAL_Kv_Set_Int(HIGHEST_TEMP_TAG, *maxTemperaturePtr);  
        if (ret != ESP_OK) {  
            EXAMPLE_TRACE("设置maxTemperature失败,%d", ret);  
        } else{
            EXAMPLE_TRACE("设置maxTemperature成功"); 
        }
    }

    // int maxTemprature = CONFIG_MAX_TEMPRATURE;
  
    // topic_len = strlen(fmt) + strlen(DEMO_PRODUCT_KEY) + strlen(DEMO_DEVICE_NAME) + 1;
    // topic = HAL_Malloc(topic_len);
    // if (topic == NULL) {
    //     EXAMPLE_TRACE("memory not enough");
    //     return -1;
    // }
    // int ret = HAL_Kv_Get_Int("maxTemprature", maxTemprature);
    // if(ret == ESP_FAIL){
    //     EXAMPLE_TRACE("获取失败");
    //     maxTemprature = CONFIG_MAX_TEMPRATURE;
    //     ret = HAL_Kv_Set_Int("maxTemprature", CONFIG_MAX_TEMPRATURE);
    //     if(ret == ESP_FAIL){
    //         EXAMPLE_TRACE("设置失败");
    //     }
    // }

    // memset(topic, 0, topic_len);
    // HAL_Snprintf(topic, topic_len, fmt, DEMO_PRODUCT_KEY, DEMO_DEVICE_NAME);

    // ESP_LOGI(TAG, "最高温度: %02d.%02d 摄氏度", *maxTemperaturePtr / 100, *maxTemperaturePtr % 100); //调试，即将注释
  
    // 使用cJSON创建JSON对象  
    root = cJSON_CreateObject();  
    cJSON_AddStringToObject(root, "method", "thing.event.property.post");  
    cJSON_AddNumberToObject(root, "id", 2222);  
    cJSON_AddObjectToObject(root, "params");  
  
    cJSON *params = cJSON_GetObjectItemCaseSensitive(root, "params");  
    if (temperature == REBOOT_EXCEPTION) {  
        cJSON_AddStringToObject(params, "data", "请重新插拔传感器的所有引脚，并等待至少1分钟，多次失败请更换传感器或联系管理员");  
        cJSON_AddNumberToObject(params, "status", REBOOT_EXCEPTION);  
    } else if (temperature == GLOBAL_EXCEPTION) {  
        cJSON_AddStringToObject(params, "data", "发生异常，请检查设备接线，并等待屏幕出现其他信息");  
        cJSON_AddNumberToObject(params, "status", GLOBAL_EXCEPTION);  
    } else if (temperature == -401) {  
        cJSON_AddStringToObject(params, "data", "WIFI密码错误，请重新配网");  
        cJSON_AddNumberToObject(params, "status", -401);  //无效，没网络发不了消息
    } else if (temperature > *maxTemperaturePtr) {  
        char *str = (char *)malloc(150);  
        if (str != NULL) {  
            sprintf(str, "温度过高,已超过 %02d.%02d 摄氏度", *maxTemperaturePtr / 100, *maxTemperaturePtr % 100);  
            // ... 使用str创建JSON对象 ...  
            cJSON_AddStringToObject(params, "data", str);  
            cJSON_AddNumberToObject(params, "status", temperature); 
            free(str); // 释放动态分配的内存  
        } else {  
            EXAMPLE_TRACE("memory not enough for message string");  
        }
        // char *str = (char *)malloc(150);
        // sprintf(str, "温度过高,已超过 %02d.%02d 摄氏度", maxTemprature / 100, maxTemprature % 100);
        // 温度显示
        ESP_LOGI(TAG, "-----第(%d)次温度上报(温度过高)-----", (update_count + 1));
        ESP_LOGI(TAG, "温度: %02d.%02d 摄氏度,已超过 %02d.%02d 摄氏度", temperature / 100, temperature % 100, 
         *maxTemperaturePtr / 100, *maxTemperaturePtr % 100); //后端处理范本
        ESP_LOGI(TAG, "-----------------------");       
        printf("\n");
        // EXAMPLE_TRACE("-----第(%d)次温度上报-----", (update_count + 1));
        // EXAMPLE_TRACE("温度: %02d.%02d 摄氏度", temprature / 100, temprature % 100); //拼写错误
        // EXAMPLE_TRACE("-----------------------\n");       
        // printf("\n"); 
    } else {  
        cJSON_AddStringToObject(params, "data", "OK");  
        cJSON_AddNumberToObject(params, "status", temperature); 
        // 温度显示
        ESP_LOGI(TAG, "-----第(%d)次温度上报-----", (update_count + 1));
        ESP_LOGI(TAG, "温度: %02d.%02d 摄氏度", temperature / 100, temperature % 100); //后端处理范本
        ESP_LOGI(TAG, "-----------------------");       
        printf("\n");
        // EXAMPLE_TRACE("-----第(%d)次温度上报-----", (update_count + 1));
        // EXAMPLE_TRACE("温度: %02d.%02d 摄氏度", temprature / 100, temprature % 100); //拼写错误
        // EXAMPLE_TRACE("-----------------------\n");       
        // printf("\n"); 
    }  
    cJSON_AddStringToObject(root, "version", "1.0.0");  
  
    // 将cJSON对象转换为字符串  
    payload = cJSON_Print(root);  


    // ESP_LOGI("PRINT", "%s\n%s", (topic),(payload));


    // 发布MQTT消息  
    res = IOT_MQTT_Publish_Simple(0, topic, IOTX_MQTT_QOS0, payload, strlen(payload));  
    if (res < 0) {  
        EXAMPLE_TRACE("publish failed, res = %d", res);  
    }

    // size_t free_heap = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);  
    // ESP_LOGE(TAG, "Free heap size: %zu bytes", free_heap);


    // 释放资源  
    cJSON_Delete(root);  
    HAL_Free(payload);  
    HAL_Free(topic);  
    // 释放资源 
    free(maxTemperaturePtr);
  
    return res;  
}

void light_event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) // rename
{
    EXAMPLE_TRACE("msg->event_type : %d", msg->event_type);
}

// --------------

// static void send_packet()
// {
//     /* Publish the MQTT packet according to the LED state (ON or OFF) */
//     uint8_t onlineStat = !LED_stat;
//     light_publish(pclient, onlineStat);
//     // IOT_MQTT_Yield(pclient, 200);
// }





int mqtt_main(void *paras)
{
    int                     res = 0;
    int                     loop_cnt = 0;
    iotx_mqtt_param_t       mqtt_params;
    
    HAL_GetProductKey(DEMO_PRODUCT_KEY);
    HAL_GetDeviceName(DEMO_DEVICE_NAME);
    HAL_GetDeviceSecret(DEMO_DEVICE_SECRET);

    EXAMPLE_TRACE("UART_temp_measurement_moudle");

    memset(&mqtt_params, 0x0, sizeof(mqtt_params));

    mqtt_params.handle_event.h_fp = light_event_handle;


    pclient = IOT_MQTT_Construct(&mqtt_params);
    if (NULL == pclient) {
        EXAMPLE_TRACE("MQTT construct failed");
        return -1;
    }

    res = light_subscribe(pclient);
    if (res < 0) {
        IOT_MQTT_Destroy(&pclient);
        return -1;
    }

    while (1) {
        key_scan(); // 按键检测
        // esp_task_wdt_reset(); // 没用 已注释

        // 没用 已注释
        // if (-1 == loop_cnt){
        //     // ......
        //     vTaskDelay(HB_INTERVAL * 1 / portTICK_PERIOD_MS); 
        //     loop_cnt = 0;
        // }
        // 没用 已注释

        if (loop_cnt % (MEASURE_INTERVAL * UPDATE_INTERVAL * 10) == 50) {
            // TODO: 在my_uart.c中实现温度传感器数据上报
            light_publish(pclient, get_temprature()); 
            ESP_LOGI(TAG, "-----第(%d)次温度上报结束-----\n", update_count + 1);  
            update_count += 1;
            // printf("%d\n", loop_cnt);
        }

        if (10000 == loop_cnt) {
            loop_cnt = 0;
        }
        // 必须写在主循环中
        IOT_MQTT_Yield(pclient, HB_INTERVAL);
        
        loop_cnt += 1;
        // printf("%d\n", loop_cnt);
    }

    return 0;
}

